﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Export.Ui.ViewModel
{
    using DatabaseCore;
    using FirstFloor.ModernUI.Presentation;
    using GalaSoft.MvvmLight;
    using FirstFloor.ModernUI.Windows.Controls;
    using System.Collections.ObjectModel;
    using System.Windows;
    using System.Data;
    using DatabaseCore.Dto;
    using Export.Ui.ServiceReferenceSAP;
    using System.Windows.Controls;
    using System.Transactions;
    using SystemCore;
    using Export.Ui.ViewModel.Order;

    public class OrderDetailViewModel
    {
        private ObservableCollection<OrderDetail> _orderDetails = new ObservableCollection<OrderDetail>();
        private OrderDetailDao orderDetailProvider = new OrderDetailDao();
        private ProdQueueDao prodQueueProvider = new ProdQueueDao();
        private ProductQueueMappedDao productQueueMappedProvider = new ProductQueueMappedDao();
        private OrderDao orderProvider = new OrderDao();
        private TransactionDao transactionProvider = new TransactionDao();

        private tbl_Order order;
        public string _orderNo = string.Empty;
        private List<tbl_OrderDetail> deleteOrderDetail;
        UserContext _userContext = null;
        SapWebServiceSoapClient webService = new ServiceReferenceSAP.SapWebServiceSoapClient();

        public OrderDetailViewModel(string orderId, OrderAllViewModel oavm)
        {
            InitialData(orderId, 0);
            initialCommand();
            initialCaption();
            OAVM = oavm;
            _orderNo = orderId;
            order = orderProvider.GetByKey(_orderNo);
            InitialSecurity();
        }

        public ObservableCollection<OrderDetail> OrdersDetails
        {
            get
            {
                return _orderDetails;
            }
            set
            {
                _orderDetails = value;
            }
        }

        public bool IsGridReadOnly { get; private set; }

        public bool IsMenuEnable { get; set; }

        public Visibility VisibilityReject { get; set; }

        public bool IsEnableCheckStock { get; set; }

        public bool IsEnableApprove { get; set; }

        public bool IsEnableSave { get; set; }

        public bool IsEnable { get { return !IsGridReadOnly; } }

        public string CaptionApprove { get; set; }

        public List<Atp> Atps { get; private set; }

        public RelayCommand SaveCommand { get; set; }
        public RelayCommand CloseCommand { get; set; }
        public RelayCommand UpdateStockCommand { get; set; }
        public RelayCommand ShowAptDetailCommand { get; set; }
        public RelayCommand ApproveCommand { get; private set; }
        public RelayCommand AddNewOrderDetailCommand { get; private set; }
        public RelayCommand DeleteOrderDetailCommand { get; private set; }
        public RelayCommand RejectCommand { get; private set; }

        public OrderAllViewModel OAVM { get; set; }
        public ModernDialog AtpDetailDialog { get; set; }
        public ModernDialog NewOrderDetailDialog { get; set; }
        public ModernDialog OrderCommentDialog { get; set; }

        private void initialCommand()
        {
            SaveCommand = new RelayCommand(Save);
            CloseCommand = new RelayCommand(Close);
            UpdateStockCommand = new RelayCommand(UpdateStock);
            ShowAptDetailCommand = new RelayCommand(ShowAtpDetail);
            ApproveCommand = new RelayCommand(ApproveOrSendToApprove);
            AddNewOrderDetailCommand = new RelayCommand(ShowAddNewOrderDetail);
            DeleteOrderDetailCommand = new RelayCommand(DeleteOrderDetail);
            RejectCommand = new RelayCommand(Reject);
        }

        private void InitialData(string orderId, int atp)
        {
            _orderDetails.Clear();
            var orders = orderDetailProvider.SearchByOrderNo(orderId);
            foreach (var order in orders)
            {
                var orderDetail = new OrderDetail(order);
                orderDetail.Atp = atp;
                _orderDetails.Add(orderDetail);
            }
        }

        private void InitialSecurity()
        {
            switch ((SystemCore.EOrderStatus)order.Status)
            {
                case EOrderStatus.All:

                    break;
                case EOrderStatus.Order:
                    if ((ERole)UserContext.Role == ERole.Approver)
                    {
                        IsGridReadOnly = true;
                        IsMenuEnable = false;
                        VisibilityReject = Visibility.Collapsed;
                        IsEnableCheckStock = false;
                        IsEnableApprove = false;
                        IsEnableSave = false;
                    }
                    else
                    {
                        IsGridReadOnly = false;
                        IsMenuEnable = true;
                        VisibilityReject = Visibility.Collapsed;
                        IsEnableCheckStock = true;
                        IsEnableApprove = true;
                        IsEnableSave = true;
                    }
                    break;
                case EOrderStatus.WaitForApprove:
                    if ((ERole)UserContext.Role == ERole.Approver)
                    {
                        IsGridReadOnly = false;
                        IsMenuEnable = true;
                        VisibilityReject = Visibility.Visible;
                        IsEnableCheckStock = true;
                        IsEnableApprove = true;
                        IsEnableSave = true;
                    }
                    else
                    {
                        IsGridReadOnly = true;
                        IsMenuEnable = false;
                        VisibilityReject = Visibility.Collapsed;
                        IsEnableCheckStock = false;
                        IsEnableApprove = false;
                        IsEnableSave = false;
                    }
                    break;
                case EOrderStatus.Queue:
                    IsGridReadOnly = true;
                    IsMenuEnable = false;
                    VisibilityReject = Visibility.Collapsed;
                    IsEnableCheckStock = false;
                    IsEnableApprove = false;
                    IsEnableSave = false;
                    break;
                case EOrderStatus.Reject:
                    if ((ERole)UserContext.Role == ERole.Approver)
                    {
                        IsGridReadOnly = true;
                        IsMenuEnable = false;
                        VisibilityReject = Visibility.Collapsed;
                        IsEnableCheckStock = false;
                        IsEnableApprove = false;
                        IsEnableSave = false;
                    }
                    else
                    {
                        IsGridReadOnly = false;
                        IsMenuEnable = true;
                        VisibilityReject = Visibility.Collapsed;
                        IsEnableCheckStock = true;
                        IsEnableApprove = true;
                        IsEnableSave = true;
                    }
                    break;
                case EOrderStatus.Closed:
                    IsGridReadOnly = true;
                    IsMenuEnable = false;
                    VisibilityReject = Visibility.Collapsed;
                    IsEnableCheckStock = false;
                    IsEnableApprove = false;
                    IsEnableSave = false;
                    break;
                default:
                    break;
            }
        }

        private void Save(object parameter)
        {
            using (var ts = new TransactionScope())
            {
                bool result = SaveOrderDetail();

                if (result)
                {
                    ts.Complete();
                    MessageBox.Show("Save order detail success");
                }
                else
                {
                    MessageBox.Show("Save order detail failed", "", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        private void DeleteOrderDetail(object parameter)
        {
            if (parameter != null)
            {
                OrderDetail selected = (OrderDetail)parameter;
                MessageBoxResult messageBoxResult = MessageBox.Show("Delete Material No '" + selected.MaterialNo + "' with QTY = " + selected.Qty, "Delete Confirmation", System.Windows.MessageBoxButton.YesNo);
                if (messageBoxResult == MessageBoxResult.Yes)
                {
                    if (deleteOrderDetail == null)
                    {
                        deleteOrderDetail = new List<tbl_OrderDetail>();
                    }
                    deleteOrderDetail.Add(selected.orderDetail);
                    _orderDetails.Remove(selected);
                }
            }
        }

        private bool SaveOrderDetail()
        {
            var listOrderDetail = new List<tbl_OrderDetail>();
            foreach (var item in OrdersDetails)
            {
                listOrderDetail.Add(item.orderDetail);
            }

            bool UpdateResult = orderDetailProvider.Update(new List<tbl_OrderDetail>(listOrderDetail), _orderNo, "system");

            bool deleteResult = true;
            if (deleteOrderDetail != null && deleteOrderDetail.Count > 0)
            {
                deleteResult = orderDetailProvider.Delete(deleteOrderDetail);
            }

            return UpdateResult && deleteResult;
        }

        private void Close(object parameter)
        {
            OAVM.dialog.Close();
        }

        private void UpdateStock(object parameter)
        {
            SAPServiceTest.SAPServiceSoapClient sapSVTest = new SAPServiceTest.SAPServiceSoapClient();
            SAPServiceTest.RequestStockEntity rq = new SAPServiceTest.RequestStockEntity();
            //var hd = new
            var hd = new SAPServiceTest.RecordHeaderEntity();
            //hd.MaterialDocNo = "ZZ1100500005035035";
            hd.RequestBy = "User1";
            rq.RecHeader = hd;
            var item = new SAPServiceTest.RequestStockItemEntity();
            item.MaterialNo = "ZZ1100704105018018";
            item.Plant = "8781";
            item.StockType = "A";

            SAPServiceTest.RequestStockItemEntity[] items = { item };
            rq.RequestStockItem = items;

            //.MaterialDocNo = "ZZ1100500005035035";
            var resuql = sapSVTest.GetStock(rq);

            var a = new OGA.NPI.CSH.SAPBLL.BLL.GTBLL("1", "");
            var con = Settings.Default.ConnectionString;
            OGA.NPI.CSH.SAPBLL.Setting.WSSetting.SetWSGTProcess(Settings.Default.OGA_NPI_CSH_SAPBLL_WRSAPService_GIProcess);
            OGA.NPI.ICSH.ServiceBase.Entities.RecordHeaderEntity processheader = a.GetProcessIDForGoodsTransferBetweenSite("1");

            OGA.NPI.ICSH.ServiceBase.Entities.RequestGoodsMovementEntity reqgment = new OGA.NPI.ICSH.ServiceBase.Entities.RequestGoodsMovementEntity();
            //SAPServiceTest.RequestGoodsMovementItemEntity reqgmentitem = new SAPServiceTest.RequestGoodsMovementItemEntity();

            OGA.NPI.ICSH.ServiceBase.Entities.RequestGoodsMovementItemEntity reqgmentitem = new OGA.NPI.ICSH.ServiceBase.Entities.RequestGoodsMovementItemEntity();
            reqgmentitem.MaterialNo = "ZZ1100704105018018";
            reqgmentitem.EntryQty = 1;
            reqgmentitem.EntryUOM = "PC";
            reqgmentitem.Plant = "8781";
            reqgmentitem.StorageLocation = "0001";
            reqgmentitem.PlantDest = "8771";
            reqgmentitem.StorageLocationDest = "0001";
            reqgmentitem.GRShipTo = "I47";
            reqgment.RequestGoodsMovementItem.Add(reqgmentitem);
            reqgment.DocDate = DateTime.Today.ToString("yyyyMMdd");
            reqgment.PostingDate = DateTime.Today.ToString("yyyyMMdd");

            processheader.ProcessID = processheader.ProcessID + 1000000;
            reqgment.RecHeader = processheader;
            var resual2 = a.GoodsTransferBetweenSite(reqgment);
            // foreach (var orderDetail in OrdersDetails)
            // {
            //     List<Atp> atps = new List<Atp>();

            //     rq.RecHeader = 'ZZ1100500005035035';
            ////     rq.PlantCode = '8781';
            ////     rq.StorageCode = Me.txtStorage.Text.Trim
            ////     rq.StockType = Me.cmbStockType.Text.Trim
            ////     rq.Unit = Me.txtUnit.Text.Trim
            ////     rq.RequestBy = "User01";


            // //resultEnt = ws.GetSAPStock(requestEnt) 'เรียกฟังก์ชัน GetSAPStock โดยส่ง requestEnt เป็น parameter
            //    // rq.RecHeader.
            //     DataTable dt = ( //webService.GetAtpData(orderDetail.MaterialNo);
            //     for (int i = 0; i < dt.Rows.Count; i++)
            //     {
            //         atps.Add(new Atp(dt.Rows[i]));
            //     }

            //     var maxAtp = atps.Max(atp => atp.ATPQty);
            //     orderDetail.Atp = maxAtp;
            //     orderDetail.Plant = atps.FirstOrDefault(atp => atp.ATPQty == maxAtp).Plant;
            // }
        }

        private void ShowAtpDetail(object parameter)
        {
            OrderDetail order = (OrderDetail)parameter;
            List<Atp> atps = new List<Atp>();
            DataTable dt = webService.GetAtpData(order.MaterialNo);
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                atps.Add(new Atp(dt.Rows[i]));
            }

            var aptDetailVM = new AtpDetailViewModel(this, atps);
            AtpDetailDialog = new ModernDialog
            {
                Title = "ATP Detail",
                Content = new Pages.AtpDetailView(aptDetailVM),
                // SizeToContent = System.Windows.SizeToContent.Manual,
                MinWidth = 500,
                MinHeight = 300
            };
            //Button hidden = new ModernButton();
            //hidden.Visibility = System.Windows.Visibility.Hidden;
            AtpDetailDialog.Buttons = new Button[] { AtpDetailDialog.OkButton };
            AtpDetailDialog.ShowDialog();

            order.Plant = aptDetailVM.SelectedPlant;
            order.Atp = aptDetailVM.SelectedAtp;
        }

        private void ShowAddNewOrderDetail(object parameter)
        {
            var newOrderDetailVm = new NewOrderDetailViewModel(this);
            NewOrderDetailDialog = new ModernDialog
            {
                Title = "New Order Detail",
                Content = new Pages.Order.NewOrderDetail(newOrderDetailVm),
                // SizeToContent = System.Windows.SizeToContent.Manual,
                MinWidth = 500,
                MinHeight = 300
            };
            Button hidden = new ModernButton();
            hidden.Visibility = System.Windows.Visibility.Hidden;
            NewOrderDetailDialog.Buttons = new Button[] { hidden };
            NewOrderDetailDialog.ShowDialog();

            if (newOrderDetailVm.IsAdd)
            {
                OrdersDetails.Add(newOrderDetailVm.NewOrderDetail);
            }
        }

        private void initialCaption()
        {
            if (UserContext.IsLoggedIn())
            {
                switch ((SystemCore.ERole)UserContext.Role)
                {
                    case ERole.SC:
                        CaptionApprove = "Send to approve";
                        break;
                    case ERole.Approver:
                        CaptionApprove = "Approve";
                        break;
                    default:
                        CaptionApprove = "";
                        break;
                }
            }
        }

        private void ApproveOrSendToApprove(object parameter)
        {
            if (UserContext.IsLoggedIn())
            {
                switch ((SystemCore.ERole)UserContext.Role)
                {
                    case ERole.SC:
                        SendToApprove(parameter); ;
                        break;
                    case ERole.Approver:
                        Approve(parameter);
                        break;
                    default:
                        CaptionApprove = "";
                        break;
                }
            }
        }

        private void SendToApprove(object parameter)
        {
            MessageBoxResult messageBoxResult = MessageBox.Show("Send to Approve order number " + order.RefOrderNo, "Send to Approve Confirmation", System.Windows.MessageBoxButton.YesNo);
            if (messageBoxResult == MessageBoxResult.Yes)
            {
                using (var ts = new TransactionScope())
                {
                    //Save detail
                    SaveOrderDetail();

                    List<tbl_Transaction> transaction = new List<tbl_Transaction>();
                    var orderDetails = orderDetailProvider.SearchByOrderNo(order.OrderNo);
                    foreach (var detail in orderDetails)
                    {
                        //Transaction
                        transaction.Add(new tbl_Transaction
                        {
                            OrderNo = detail.OrderNo,
                            MaterialNo = detail.MaterialNo,
                            StockNo = "",
                            Plant = detail.Plant,
                            //QtyIn = detail.ReceivedQty,
                            Qty = detail.Qty,
                            //QtyRemain = detail.ReceivedQty - detail.ReceivedQty, //QtyIn - QtyReceive
                            PalletDetailId = null,
                            UpdateBy = UserContext.FullName,
                            UpdateDate = DateTime.Now,
                        });
                    }
                    transactionProvider.InsertCollection(transaction);

                    //อัพเดต status ของ order เป็น Wait for approve
                    order.Status = (int)EOrderStatus.WaitForApprove;
                    order.UpdateBy = UserContext.FullName;
                    order.UpdateDate = DateTime.Now;
                    orderProvider.Update(order);

                    ts.Complete();

                    MessageBox.Show("Send to Approve success");

                    Close(parameter);
                }
            }
        }

        private void Approve(object parameter)
        {
            MessageBoxResult messageBoxResult = MessageBox.Show("Approve order number " + order.RefOrderNo, "Approve Confirmation", System.Windows.MessageBoxButton.YesNo);
            if (messageBoxResult == MessageBoxResult.Yes)
            {
                using (var ts = new TransactionScope())
                {
                    //Save detail
                    SaveOrderDetail();

                    // ถ้าสินค้าพอใน ATP, ก็ตัดจาก ATP ได้เลย (Closed)
                    // ถ้าพอบางส่วนก็ตัดเท่าที่มีใน ATP, ที่เหลือรอในคิว
                    // ถ้าไม่พอให้ไปรอในคิวทั้งหมด
                    bool isClosed = false;
                    bool isAllClosed = true;
                    List<ProdQueue> prodQueue = new List<ProdQueue>();
                    List<ProductQueueMapped> productQueueMapped = new List<ProductQueueMapped>();
                    List<tbl_Transaction> transaction = new List<tbl_Transaction>();

                    var orderDetails = orderDetailProvider.SearchByOrderNo(order.OrderNo);
                    foreach (var detail in orderDetails)
                    {
                        isClosed = false;

                        if (!string.IsNullOrEmpty(detail.MaterialNo))
                        {
                            //สินค้าที่ได้รับ
                            if (detail.ReceivedQty != 0)
                            {
                                //เซฟลง ProductQueueMapped ว่าตัดสต็อกไปได้แล้ว
                                productQueueMapped.Add(new ProductQueueMapped
                                {
                                    ProductId = detail.MaterialNo,
                                    PlantCode = detail.Plant,
                                    OrderNo = detail.OrderNo,
                                    Qty = detail.ReceivedQty,
                                });
                            }

                            //สินค้าที่รอในคิว
                            if (detail.RemainingQty != 0)
                            {
                                //ไปรอในคิว ProdQueue
                                prodQueue.Add(new ProdQueue
                                {
                                    ProductCode = detail.MaterialNo,
                                    PlantCode = detail.Plant,
                                    OrderNo = detail.OrderNo,
                                    Qty = detail.RemainingQty,
                                    Date = DateTime.Now,
                                    IsActive = true,
                                    Rate = detail.Rate,
                                    ValidFrom = detail.ValidFrom,
                                    ValidTo = detail.ValidTo,
                                });
                            }

                            //Transaction
                            transaction.Add(new tbl_Transaction
                            {
                                OrderNo = detail.OrderNo,
                                MaterialNo = detail.MaterialNo,
                                StockNo = "",
                                Plant = detail.Plant,
                                //QtyIn = detail.ReceivedQty,
                                Qty = -detail.ReceivedQty,
                                //QtyRemain = detail.ReceivedQty - detail.ReceivedQty, //QtyIn - QtyReceive
                                PalletDetailId = null,
                                UpdateBy = "ATP",
                                UpdateDate = DateTime.Now,
                            });
                        }

                        if (detail.RemainingQty == 0)
                        {
                            //ปิด Order Detail
                            isClosed = true;
                        }

                        //Order closed?
                        isAllClosed = isAllClosed && isClosed;
                    }

                    bool isSuccessProdQueue = prodQueueProvider.InsertCollection(prodQueue);
                    bool isSuccessProductQueueMapped = productQueueMappedProvider.InsertCollection(productQueueMapped);
                    transactionProvider.InsertCollection(transaction);

                    //อัพเดต status ของ order
                    order.Status = isAllClosed ? (int)EOrderStatus.Closed : (int)EOrderStatus.Queue;
                    order.UpdateBy = UserContext.FullName;
                    order.UpdateDate = DateTime.Now;
                    orderProvider.Update(order);

                    ts.Complete();

                    MessageBox.Show("Approve success");

                    Close(parameter);
                }
            }
        }

        private void Reject(object parameter)
        {
            var orderCommentVm = new OrderCommentViewModel(this);
            OrderCommentDialog = new ModernDialog
            {
                Title = "Order Comment",
                Content = new Pages.Order.OrderComment(orderCommentVm),
                // SizeToContent = System.Windows.SizeToContent.Manual,
                MinWidth = 500,
                MinHeight = 300
            };
            Button hidden = new ModernButton();
            hidden.Visibility = System.Windows.Visibility.Hidden;
            OrderCommentDialog.Buttons = new Button[] { hidden };
            OrderCommentDialog.ShowDialog();

            if (orderCommentVm.IsReject)
            {
                using (var ts = new TransactionScope())
                {
                    //อัพเดต status ของ order เป็น Reject
                    var comment = orderCommentVm.Comment;
                    var orderStatus = (int)EOrderStatus.Reject;

                    orderProvider.UpdateOrderStatusAndComment(_orderNo, orderStatus, comment, UserContext.FullName);

                    ts.Complete();

                    MessageBox.Show("Reject success");
                    Close(parameter);
                }
            }
        }
    }
}
